home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / XFORM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-20  |  18.0 KB  |  512 lines

  1. /* $Id: xform.c,v 3.3 1998/08/20 04:15:48 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: xform.c,v $
  26.  * Revision 3.3  1998/08/20 04:15:48  brianp
  27.  * added prototype 3.1 transformation functions
  28.  *
  29.  * Revision 3.2  1998/04/18 05:00:56  brianp
  30.  * renamed USE_ASM to USE_X86_ASM
  31.  *
  32.  * Revision 3.1  1998/02/01 16:37:19  brianp
  33.  * added GL_EXT_rescale_normal extension
  34.  *
  35.  * Revision 3.0  1998/01/31 21:08:31  brianp
  36.  * initial rev
  37.  *
  38.  */
  39.  
  40.  
  41. /*
  42.  * Matrix/vertex/vector transformation stuff
  43.  *
  44.  *
  45.  * NOTES:
  46.  * 1. 4x4 transformation matrices are stored in memory in column major order.
  47.  * 2. Points/vertices are to be thought of as column vectors.
  48.  * 3. Transformation of a point p by a matrix M is: p' = M * p
  49.  *
  50.  */
  51.  
  52.  
  53. #ifdef PC_HEADER
  54. #include "all.h"
  55. #else
  56. #include <math.h>
  57. #include "context.h"
  58. #include "mmath.h"
  59. #include "types.h"
  60. #include "xform.h"
  61. #endif
  62.  
  63.  
  64.  
  65. /*
  66.  * Apply a transformation matrix to an array of [X Y Z W] coordinates:
  67.  *   for i in 0 to n-1 do   q[i] = m * p[i]
  68.  * where p[i] and q[i] are 4-element column vectors and m is a 16-element
  69.  * transformation matrix.
  70.  */
  71. void gl_xform_points_4fv( GLuint n, GLfloat q[][4], const GLfloat m[16],
  72.                           GLfloat p[][4] )
  73. {
  74.    /* This function has been carefully crafted to maximize register usage
  75.     * and use loop unrolling with IRIX 5.3's cc.  Hopefully other compilers
  76.     * will like this code too.
  77.     */
  78.    {
  79.       GLuint i;
  80.       GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  81.       GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  82.       if (m12==0.0F && m13==0.0F) {
  83.          /* common case */
  84.          for (i=0;i<n;i++) {
  85.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  86.             q[i][0] = m0 * p0 + m4  * p1 + m8 * p2;
  87.             q[i][1] = m1 * p0 + m5  * p1 + m9 * p2;
  88.          }
  89.       }
  90.       else {
  91.          /* general case */
  92.          for (i=0;i<n;i++) {
  93.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2], p3 = p[i][3];
  94.             q[i][0] = m0 * p0 + m4  * p1 + m8 * p2 + m12 * p3;
  95.             q[i][1] = m1 * p0 + m5  * p1 + m9 * p2 + m13 * p3;
  96.          }
  97.       }
  98.    }
  99.    {
  100.       GLuint i;
  101.       GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  102.       GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  103.       if (m3==0.0F && m7==0.0F && m11==0.0F && m15==1.0F) {
  104.          /* common case */
  105.          for (i=0;i<n;i++) {
  106.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2], p3 = p[i][3];
  107.             q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14 * p3;
  108.             q[i][3] = p3;
  109.          }
  110.       }
  111.       else {
  112.          /* general case */
  113.          for (i=0;i<n;i++) {
  114.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2], p3 = p[i][3];
  115.             q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14 * p3;
  116.             q[i][3] = m3 * p0 + m7 * p1 + m11 * p2 + m15 * p3;
  117.          }
  118.       }
  119.    }
  120. }
  121.  
  122.  
  123.  
  124. /*
  125.  * Apply a transformation matrix to an array of [X Y Z] coordinates:
  126.  *   for i in 0 to n-1 do   q[i] = m * p[i]
  127.  */
  128. void gl_xform_points_3fv( GLuint n, GLfloat q[][4], const GLfloat m[16],
  129.                           GLfloat p[][3] )
  130. {
  131.    /* This function has been carefully crafted to maximize register usage
  132.     * and use loop unrolling with IRIX 5.3's cc.  Hopefully other compilers
  133.     * will like this code too.
  134.     */
  135.    {
  136.       GLuint i;
  137.       GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  138.       GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  139.       for (i=0;i<n;i++) {
  140.          GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  141.          q[i][0] = m0 * p0 + m4  * p1 + m8 * p2 + m12;
  142.          q[i][1] = m1 * p0 + m5  * p1 + m9 * p2 + m13;
  143.       }
  144.    }
  145.    {
  146.       GLuint i;
  147.       GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  148.       GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  149.       if (m3==0.0F && m7==0.0F && m11==0.0F && m15==1.0F) {
  150.          /* common case */
  151.          for (i=0;i<n;i++) {
  152.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  153.             q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14;
  154.             q[i][3] = 1.0F;
  155.          }
  156.       }
  157.       else {
  158.          /* general case */
  159.          for (i=0;i<n;i++) {
  160.             GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  161.             q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14;
  162.             q[i][3] = m3 * p0 + m7 * p1 + m11 * p2 + m15;
  163.          }
  164.       }
  165.    }
  166. }
  167.  
  168.  
  169.  
  170. #ifndef USE_X86_ASM
  171. /*
  172.  * Apply a transformation matrix to an array of normal vectors:
  173.  *   for i in 0 to n-1 do  v[i] = u[i] * m
  174.  * where u[i] and v[i] are 3-element row vectors and m is a 16-element
  175.  * transformation matrix.
  176.  * If the normalize flag is true the normals will be scaled to length 1.
  177.  * If the rescale flag is true then do normal rescaling.
  178.  */
  179. void gl_xform_normals_3fv( GLuint n, GLfloat v[][3], const GLfloat m[16],
  180.                            GLfloat u[][3], GLboolean normalize,
  181.                            GLboolean rescale )
  182. {
  183.    if (normalize) {
  184.       if (rescale) {
  185.          /* Transform normals, rescale and normalize */
  186.          GLuint i;
  187.          GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
  188.          GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
  189.          GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
  190.          GLfloat f = GL_SQRT( m2*m2 + m6*m6 + m10*m10 );
  191.          f = (f == 0.0F) ? 1.0F : (1.0F / f);
  192.          for (i=0;i<n;i++) {
  193.             GLdouble tx, ty, tz;
  194.             {
  195.                GLfloat ux = u[i][0],  uy = u[i][1],  uz = u[i][2];
  196.                tx = f * (ux * m0 + uy * m1 + uz * m2);
  197.                ty = f * (ux * m4 + uy * m5 + uz * m6);
  198.                tz = f * (ux * m8 + uy * m9 + uz * m10);
  199.             }
  200.             {
  201.                GLdouble len, scale;
  202.                len = GL_SQRT( tx*tx + ty*ty + tz*tz );
  203.                scale = (len>1E-30) ? (1.0 / len) : 1.0;
  204.                v[i][0] = tx * scale;
  205.                v[i][1] = ty * scale;
  206.                v[i][2] = tz * scale;
  207.             }
  208.          }
  209.       }
  210.       else {
  211.          /* Transform and normalize */
  212.          GLuint i;
  213.          GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
  214.          GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
  215.          GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
  216.          for (i=0;i<n;i++) {
  217.             GLdouble tx, ty, tz;
  218.             {
  219.                GLfloat ux = u[i][0],  uy = u[i][1],  uz = u[i][2];
  220.                tx = ux * m0 + uy * m1 + uz * m2;
  221.                ty = ux * m4 + uy * m5 + uz * m6;
  222.                tz = ux * m8 + uy * m9 + uz * m10;
  223.             }
  224.             {
  225.                GLdouble len, scale;
  226.                len = GL_SQRT( tx*tx + ty*ty + tz*tz );
  227.                scale = (len>1E-30) ? (1.0 / len) : 1.0;
  228.                v[i][0] = tx * scale;
  229.                v[i][1] = ty * scale;
  230.                v[i][2] = tz * scale;
  231.             }
  232.          }
  233.       }
  234.    }
  235.    else {
  236.       if (rescale) {
  237.          /* Transform and rescale */
  238.          GLuint i;
  239.          GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
  240.          GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
  241.          GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
  242.          GLfloat f = GL_SQRT( m2*m2 + m6*m6 + m10*m10 );
  243.          f = (f == 0.0F) ? 1.0F : (1.0F / f);
  244.          for (i=0;i<n;i++) {
  245.             GLfloat ux = u[i][0],  uy = u[i][1],  uz = u[i][2];
  246.             v[i][0] = f * (ux * m0 + uy * m1 + uz * m2);
  247.             v[i][1] = f * (ux * m4 + uy * m5 + uz * m6);
  248.             v[i][2] = f * (ux * m8 + uy * m9 + uz * m10);
  249.          }
  250.       }
  251.       else {
  252.          /* Just transform */
  253.          GLuint i;
  254.          GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
  255.          GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
  256.          GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
  257.          for (i=0;i<n;i++) {
  258.             GLfloat ux = u[i][0],  uy = u[i][1],  uz = u[i][2];
  259.             v[i][0] = ux * m0 + uy * m1 + uz * m2;
  260.             v[i][1] = ux * m4 + uy * m5 + uz * m6;
  261.             v[i][2] = ux * m8 + uy * m9 + uz * m10;
  262.          }
  263.       }
  264.    }
  265. }
  266. #endif
  267.  
  268.  
  269. /*
  270.  * Transform a 4-element row vector (1x4 matrix) by a 4x4 matrix.  This
  271.  * function is used for transforming clipping plane equations and spotlight
  272.  * directions.
  273.  * Mathematically,  u = v * m.
  274.  * Input:  v - input vector
  275.  *         m - transformation matrix
  276.  * Output:  u - transformed vector
  277.  */
  278. void gl_transform_vector( GLfloat u[4], const GLfloat v[4], const GLfloat m[16] )
  279. {
  280.    GLfloat v0=v[0], v1=v[1], v2=v[2], v3=v[3];
  281. #define M(row,col)  m[col*4+row]
  282.    u[0] = v0 * M(0,0) + v1 * M(1,0) + v2 * M(2,0) + v3 * M(3,0);
  283.    u[1] = v0 * M(0,1) + v1 * M(1,1) + v2 * M(2,1) + v3 * M(3,1);
  284.    u[2] = v0 * M(0,2) + v1 * M(1,2) + v2 * M(2,2) + v3 * M(3,2);
  285.    u[3] = v0 * M(0,3) + v1 * M(1,3) + v2 * M(2,3) + v3 * M(3,3);
  286. #undef M
  287. }
  288.  
  289.  
  290.  
  291. /**********************************************************************
  292.  *
  293.  * Mesa 3.1 prototype transformation code
  294.  *
  295.  * Objectives:
  296.  *     Move all functions which may be asm-accelerated out of vbxform.c
  297.  *       into this file.
  298.  *
  299.  *     Add support for arbitrary strides in source coordinates to better
  300.  *       support vertex arrays.
  301.  *
  302.  **********************************************************************/
  303.  
  304.  
  305.  
  306. /*
  307.  * Use the current modelview matrix to transform XYZ vertices from object
  308.  * to eye coordinates.
  309.  * Input:  ctx - the context
  310.  *         n - number of vertices to transform
  311.  *         stride - stride in bytes between subsequent vObj vertices
  312.  *         vObj - pointer to first vertex (in object coordinates)
  313.  * Output;  vEye - array [n][4] of eye coordinates
  314.  */
  315. void
  316. gl_transform_points3( const GLcontext *ctx, GLuint n, GLuint stride,
  317.                       const GLfloat *vObj, GLfloat vEye[][4] )
  318. {
  319.    ASSERT((stride & 0x3) == 0);  /* multiple of 4 bytes */
  320.  
  321.    switch (ctx->ModelViewMatrixType) {
  322.       case MATRIX_GENERAL:
  323.          {
  324.             const GLfloat *m = ctx->ModelViewMatrix;
  325.             const GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  326.             const GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  327.             const GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  328.             const GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  329.             GLuint i;
  330.             for (i=0;i<n;i++) {
  331.                const GLfloat ox = vObj[0], oy = vObj[1], oz = vObj[2];
  332.                vEye[i][0] = m0 * ox + m4 * oy + m8  * oz + m12;
  333.                vEye[i][1] = m1 * ox + m5 * oy + m9  * oz + m13;
  334.                vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14;
  335.                vEye[i][3] = m3 * ox + m7 * oy + m11 * oz + m15;
  336.                vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  337.             }
  338.          }
  339.          break;
  340.       case MATRIX_IDENTITY:
  341.          {
  342.             GLuint i;
  343.             for (i=0;i<n;i++) {
  344.                vEye[i][0] = vObj[0];
  345.                vEye[i][1] = vObj[1];
  346.                vEye[i][2] = vObj[2];
  347.                vEye[i][3] = 1.0F;
  348.                vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  349.             }
  350.          }
  351.          break;
  352.       case MATRIX_2D:
  353.          {
  354.             const GLfloat *m = ctx->ModelViewMatrix;
  355.             const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
  356.             const GLfloat m12 = m[12], m13 = m[13];
  357.             GLuint i;
  358.             for (i=0;i<n;i++) {
  359.                const GLfloat ox = vObj[0], oy = vObj[1], oz = vObj[2];
  360.                vEye[i][0] = m0 * ox + m4 * oy            + m12       ;
  361.                vEye[i][1] = m1 * ox + m5 * oy            + m13       ;
  362.                vEye[i][2] =                   +       oz             ;
  363.                vEye[i][3] =                                      1.0F;
  364.                vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  365.             }
  366.          }
  367.          break;
  368.       case MATRIX_2D_NO_ROT:
  369.          {
  370.             const GLfloat *m = ctx->ModelViewMatrix;
  371.             const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
  372.             GLuint i;
  373.             for (i=0;i<n;i++) {
  374.                const GLfloat ox = vObj[0], oy = vObj[1], oz = vObj[2];
  375.                vEye[i][0] = m0 * ox                      + m12       ;
  376.                vEye[i][1] =           m5 * oy            + m13       ;
  377.                vEye[i][2] =                   +       oz             ;
  378.                vEye[i][3] =                                      1.0F;
  379.                vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  380.             }
  381.          }
  382.          break;
  383.       case MATRIX_3D:
  384.          {
  385.             const GLfloat *m = ctx->ModelViewMatrix;
  386.             const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4];
  387.             const GLfloat m5 = m[5], m6 = m[6], m8 = m[8], m9 = m[9];
  388.             const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14];
  389.             GLuint i;
  390.             for (i=0;i<n;i++) {
  391.                const GLfloat ox = vObj[0], oy = vObj[1], oz = vObj[2];
  392.                vEye[i][0] = m0 * ox + m4 * oy +  m8 * oz + m12       ;
  393.                vEye[i][1] = m1 * ox + m5 * oy +  m9 * oz + m13       ;
  394.                vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14       ;
  395.                vEye[i][3] =                                      1.0F;
  396.                vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  397.             }
  398.          }
  399.          break;
  400.       default:
  401.          /* should never get here */
  402.          gl_problem( NULL, "invalid matrix type in gl_transform_points3()" );
  403.    }
  404. }
  405.  
  406.  
  407. /*
  408.  * Use the current modelview matrix to transform XYZW vertices from object
  409.  * to eye coordinates.
  410.  * Input:  ctx - the context
  411.  *         n - number of vertices to transform
  412.  *         stride - stride in bytes between subsequent vObj vertices
  413.  *         vObj - pointer to first vertex (in object coordinates)
  414.  * Output;  vEye - array [n][4] of eye coordinates
  415.  */
  416. void
  417. gl_transform_points4( const GLcontext *ctx, GLuint n, GLuint stride,
  418.                       const GLfloat *vObj, GLfloat vEye[][4] )
  419. {
  420.    ASSERT((stride & 0x3) == 0);  /* multiple of 4 bytes */
  421.  
  422.    switch (ctx->ModelViewMatrixType) {
  423.       case MATRIX_GENERAL:
  424.          {
  425.             const GLfloat *m = ctx->ModelViewMatrix;
  426.             const GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  427.             const GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  428.             const GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  429.             const GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  430.             GLuint i;
  431.             for (i=0;i<n;i++) {
  432.                const GLfloat ox = vObj[0], oy = vObj[1];
  433.                const GLfloat oz = vObj[2], ow = vObj[3];
  434.                vEye[i][0] = m0 * ox + m4 * oy + m8  * oz + m12 * ow;
  435.                vEye[i][1] = m1 * ox + m5 * oy + m9  * oz + m13 * ow;
  436.                vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
  437.                vEye[i][3] = m3 * ox + m7 * oy + m11 * oz + m15 * ow;
  438.                vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  439.             }
  440.          }
  441.          break;
  442.       case MATRIX_IDENTITY:
  443.          {
  444.             GLuint i;
  445.             for (i=0;i<n;i++) {
  446.                vEye[i][0] = vObj[0];
  447.                vEye[i][1] = vObj[1];
  448.                vEye[i][2] = vObj[2];
  449.                vEye[i][3] = vObj[3];
  450.                vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  451.             }
  452.          }
  453.          break;
  454.       case MATRIX_2D:
  455.          {
  456.             const GLfloat *m = ctx->ModelViewMatrix;
  457.             const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
  458.             const GLfloat m12 = m[12], m13 = m[13];
  459.             GLuint i;
  460.             for (i=0;i<n;i++) {
  461.                const GLfloat ox = vObj[0], oy = vObj[1];
  462.                const GLfloat oz = vObj[2], ow = vObj[3];
  463.                vEye[i][0] = m0 * ox + m4 * oy            + m12 * ow;
  464.                vEye[i][1] = m1 * ox + m5 * oy            + m13 * ow;
  465.                vEye[i][2] =                   +       oz           ;
  466.                vEye[i][3] =                                      ow;
  467.                vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  468.             }
  469.          }
  470.          break;
  471.       case MATRIX_2D_NO_ROT:
  472.          {
  473.             const GLfloat *m = ctx->ModelViewMatrix;
  474.             const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
  475.             GLuint i;
  476.             for (i=0;i<n;i++) {
  477.                const GLfloat ox = vObj[0], oy = vObj[1];
  478.                const GLfloat oz = vObj[2], ow = vObj[3];
  479.                vEye[i][0] = m0 * ox                      + m12 * ow;
  480.                vEye[i][1] =           m5 * oy            + m13 * ow;
  481.                vEye[i][2] =                   +       oz           ;
  482.                vEye[i][3] =                                      ow;
  483.                vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  484.             }
  485.          }
  486.          break;
  487.       case MATRIX_3D:
  488.          {
  489.             const GLfloat *m = ctx->ModelViewMatrix;
  490.             const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4];
  491.             const GLfloat m5 = m[5], m6 = m[6], m8 = m[8], m9 = m[9];
  492.             const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14];
  493.             GLuint i;
  494.             for (i=0;i<n;i++) {
  495.                const GLfloat ox = vObj[0], oy = vObj[1];
  496.                const GLfloat oz = vObj[2], ow = vObj[3];
  497.                vEye[i][0] = m0 * ox + m4 * oy +  m8 * oz + m12 * ow;
  498.                vEye[i][1] = m1 * ox + m5 * oy +  m9 * oz + m13 * ow;
  499.                vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
  500.                vEye[i][3] =                                      ow;
  501.                vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  502.             }
  503.          }
  504.          break;
  505.       default:
  506.          /* should never get here */
  507.          gl_problem( NULL, "invalid matrix type in gl_transform_points4()" );
  508.    }
  509. }
  510.  
  511.  
  512.